#!usr/bin/env python3
# -*- conding: utf-8 -*-

# 第八章 类和对象 P237

from datetime import date 

d1 = date(2017,6,13)

print(d1,format(d1))
'''
通常约定，单下划线的为私有变量，双下划线的是私有变量并且子类并不能覆盖重写的属性或方法。
这些只是约定，Python并没有这种限制

'''

#getter和setter的实现

class Person():
    def __init__(self,firse_name,age):
        self._firse_name = firse_name
        self.age = age

    def walk(self):
        print("I am a Person,I am walkking.")

    @property
    def first_name(self):
        return self._firse_name # getter
    
    @first_name.setter
    def first_name(self,value):
        if not isinstance(value,str):
            raise TypeError("Expected a string")
        self._firse_name = value

    @first_name.deleter
    def firse_name(self): #当属性被删除时 会执行该函数         
        raise AttributeError("Can't delete attribute")


class Boy(Person):
    def walk(self):
        super().walk()
        print("boy walk")
    
    @Person.firse_name.getter #覆盖父类的getter和setter 通常这种写法
    def firse_name(self):
        return super().firse_name


p = Person("zhou",21)
b = Boy("Hello",22)

print(b.walk(),b.firse_name)


a = 3**3 # 题外话 幂运算的快捷表示写法
print(a)

# 描述器

class Integer(object): # 定义一个描述器
    def __init__(self,name):
        self.name = name

    def __get__(self,instance,cls):
        print("__get__",instance)
        if  instance is None:
            return self
        else:
            return instance.__dict__[self.name]
        

    def __set__(self,instance,value):
        print("instance",instance)
        if not isinstance(value,int):
            raise TypeError("must int")
        instance.__dict__[self.name] = value
    
    def __delete__(self,instance):
        del instance.__dict__[self.name]
            


class Point():
    x = Integer("x") # 描述器必须是类级别的属性
    y = Integer("y")

    def __init__(self,x,y):
        self.x = x
        self.y = y

p = Point(12,30)
print(p)
print(",p.x",p.x)

# 定义抽象类 可以认为是接口

from abc import ABCMeta,abstractclassmethod

class IFollow(metaclass=ABCMeta): # 不能实例化的
    @abstractclassmethod
    def follow(self):
        pass
    
    @abstractclassmethod
    def track(self):
        pass

#代理模式

#代理类
class Proxy(object):

    def __init__(self,obj):
        self._obj = obj
    
    def __getattr__(self,name): # 所有类 如果访问实例没有的属性，那么就会访问该方法 
        return getattr(self._obj,name) # 对于双下划线的属性 大多数是不能代理的

    def __setattr__(self,name,value): 
        if name.startswith("_"): # 通常情况下是不代理下划线开头的属性 ，不过这里是保险的写法
            super().__setattr__(name,value)
        else:
            setattr(self._obj,name,value)
    
    def __delattr__(self,name):
        if name.startwith("_"):
            super().__delattr__(name)
        else:
            delattr(self._obj,name)

class SubPerson(object):
    def __init__(self):
        print("I am sub person")

    def walk(self):
        print("i am walk!")
    def anser(self,s:str):
        print(s)

sp = SubPerson()
p = Proxy(sp)

p.walk() # 代理类执行被代理类的方法

#创建不执行 __init__的实例

sp = SubPerson.__new__(SubPerson) # 不会执行构造函数

import operator

op = operator.methodcaller("anser","Hello") #通过这个操作来执行实例的函数

op(sp)